home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i051: A cat(1) for mmap'able devices
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: "K. Richard Magill" <oxtrap!rich>
- Posting-number: Volume 15, Issue 51
- Archive-name: mcat2
-
- [ I haven't tried this, but I did splice the makefile into the shar. -r$ ]
-
- This is a program that works like cat but can read or write mmap'able
- devices like sequent's pmap(4). I haven't tried it yet, but it should
- also work on devices like sun frame buffers. The version I posted
- earlier worked on dynix 2.1.1 but apparently 3.0.4 can't write/send(2)
- from mmap'd memory, (or at least pmap devices).
-
- #!/bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting test in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # makefile mcat.l mcat.c
- echo extracting makefile
- sed 's/^X//' >makefile << 'END-of-makefile'
- all: mcat mcat.l
- mcat: mcat.c
- $(CC) -o mcat $(CFLAGS) mcat.c
- install: all
- @echo install according to local convention
- END-of-makefile
- echo extracting mcat.l
- sed 's/^X//' >mcat.l << 'END-of-mcat.l'
- X.TH MCAT l "27 Nov 87" "local"
- X.SH NAME
- Xmcat \- cat like program for read/write'ing pmap devices from shell
- X.SH SYNOPSIS
- X.B mcat
- X[-b buffersize] [-i ifile] [-o ofile] [-s] [-v]
- X.SH DESCRIPTION
- X.I mcat
- Xis a program very much like cat or dd that is capable of reading a
- Xnon-read(2)'able device, for example, an mmap(2) only device like
- Xsequent's pmap devices. It is capable of copying mmap to mmap,
- Xreading and writing onto mmap or reading from mmap and writing.
- X.SH OPTIONS
- X.PP
- X.TP 14
- X.B \-b buffersize
- Xuse buffersize as the buffer size for read's and write's rather than BUFSIZ.
- X.PP
- X.TP 14
- X.B \-i ifile
- Xuse ifile as file name for input rather than stdin.
- X.PP
- X.TP 14
- X.B \-o ofile
- Xuse ofile as file name for output rather than stdout.
- X.PP
- X.TP 14
- X.B \-s
- Xprint no error messages. (silent).
- X.PP
- X.TP 14
- X.B \-v
- Xprint some log lines. (verbose).
- X.SH BUGS
- XDue to a synergy of shell strategy, and balance hardware limitations,
- Xyou can not redirect stdout to a pmap device on sequent balance. (but
- Xyou can use -o ofile).
- X.SH AUTHOR
- XK. Richard Magill - Digital Works Ltd.
- X
- Xrich@oxtrap.UUCP, rich@sendai.UUCP
- END-of-mcat.l
- echo extracting mcat.c
- sed 's/^X//' >mcat.c << 'END-of-mcat.c'
- X/*
- X * This file is mcat.c and contains a sort of cat utility for use with
- X * pmap devices. It was originally written on sequent Dynix 2.1.1.
- X *
- X * to do:
- X * mmap disk files.
- X * mcat multiple files in, out.
- X * -x write at offset x.
- X * trunc old disk files.
- X *
- X * Original Author: K. Richard Magill Fri Nov 20 16:00:53 EST 1987
- X * Last Mod Mon Mar 21 00:31:18 EST 1988, by rich@oxtrap
- X *
- X *$Header: /u1/rich/bin/src/RCS/mcat.c,v 1.2 88/03/21 00:42:41 rich Exp $
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <sys/ioctl.h>
- X#include <sys/mman.h>
- X#include <sys/stat.h>
- X#include <machine/pmap.h>
- X
- X#define Perror(s) {if(Silent==0)perror(s);}
- X
- Xextern char *optarg;
- Xextern int optind;
- X
- Xchar *malloc();
- Xchar *valloc();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X char *InBase = ((char *) 0);
- X char *OutBase = ((char *) 0);
- X
- X int BufferSize = BUFSIZ;
- X int InPut = fileno(stdin);
- X int OutPut = fileno(stdout);
- X int Silent = 0;
- X int Verbose = 0;
- X int WriteFlags = 0;
- X int c;
- X
- X struct pmap_ioc InSize, OutSize;
- X
- X/*
- X * parse args.
- X */
- X
- X while ((c = getopt(argc, argv, "b:i:o:sv")) != EOF) {
- X switch (c) {
- X
- X case 'b':
- X BufferSize = atoi(optarg);
- X
- X if (Verbose != 0) {
- X (void) fprintf(stderr, "%s: Using %d byte i/o.\n", argv[0], BufferSize);
- X } /* verbose */
- X
- X break;
- X
- X case 'i':
- X
- X if ((InPut = open(optarg, O_RDONLY, 0666)) < 0) {
- X Perror("opening input:");
- X exit(1);
- X } /* on error opening for read */
- X
- X break;
- X
- X case 'o':
- X if (access(optarg, F_OK) == 0) {
- X if (Verbose != 0) {
- X (void) fprintf(stderr, "%s: output exists.\n", argv[0]);
- X } /* verbose */
- X
- X if (access(optarg, R_OK) == 0) {
- X if (Verbose != 0) {
- X (void) fprintf(stderr, "%s: output is readable.\n", argv[0]);
- X } /* verbose */
- X
- X WriteFlags |= O_RDWR;
- X }
- X
- X } else {
- X if (Verbose != 0) {
- X (void) fprintf(stderr, "%s: output does not exist. creating.\n", argv[0]);
- X } /* verbose */
- X
- X WriteFlags = O_CREAT | O_RDWR;
- X }
- X
- X if ((OutPut = open(optarg, WriteFlags, 0666)) < 0) {
- X Perror("mcat: opening output");
- X exit(1);
- X } /* on error opening for write */
- X
- X break;
- X
- X case 's':
- X Silent = 1;
- X break;
- X
- X case 'v':
- X Verbose = 1;
- X break;
- X
- X case '?':
- X default:
- X if (Silent == 0) {
- X (void) fprintf(stderr, "%s: usage: -b buffer_size -i input_file -o output_file -s -v\n", argv[0]);
- X } /* not silent */
- X
- X exit(1);
- X
- X } /* switch on switch character */
- X } /* while there are switch characters */
- X
- X/*
- X * I presume that if the ioctl fails, this is not a pmap device and we
- X * aren't mapping. If you know of a better way to check a a descriptor
- X * for mmap'ability, (short of chasing the major number through the kernel),
- X * let me know.
- X */
- X
- X if (ioctl(InPut, PMAPIOCGETP, (char *) &InSize) == 0) { /* not pmap */
- X if ((InBase = valloc((unsigned) InSize.pi_size)) == 0) {
- X Perror("valloc'ing output buffer:");
- X exit(1);
- X } /* on error valloc'ing */
- X
- X if (mmap(InBase, (int) InSize.pi_size, PROT_READ, MAP_SHARED, InPut, 0) != 0) {
- X Perror("on error mmap'ing input:");
- X exit(1);
- X } /* on error mmap'ing input */
- X
- X if (Verbose != 0) {
- X (void) fprintf(stderr, "%s: mmap'ing input.\n",
- X argv[0]);
- X } /* verbose */
- X
- X } /* not mapped or not mappable */
- X
- X if ((ioctl(OutPut, PMAPIOCGETP, (char *) &OutSize) == 0)) { /* not mapping */
- X if ((OutBase = valloc((unsigned) OutSize.pi_size)) == 0) {
- X Perror("valloc'ing for output buffer:");
- X exit(1);
- X } /* on valloc error */
- X
- X if (mmap(OutBase, (int) OutSize.pi_size, PROT_RDWR, MAP_SHARED, OutPut, 0) != 0) {
- X Perror("mmap'ing output:");
- X
- X if (Silent == 0) {
- X (void) fprintf(stderr, "%s: remember you can't redirect output.\n", argv[0]);
- X } /* not silent */
- X
- X exit(1);
- X } /* on error mmap'ing output */
- X
- X if (Verbose != 0) {
- X (void) fprintf(stderr, "%s: mmap'ing output.\n",
- X argv[0]);
- X } /* verbose */
- X
- X } /* not mapped or not mappable */
- X
- X if (InBase != ((char *) NULL)) { /* mapping input */
- X if (OutBase != ((char *) NULL)) { /* and output */
- X (void) bcopy(InBase, OutBase, (unsigned) ((InSize.pi_size < OutSize.pi_size) ? InSize.pi_size : OutSize.pi_size));
- X } else { /* map in, no map out */
- X int ReallyWrote;
- X
- X OutBase = malloc((unsigned) BufferSize);
- X
- X while (InSize.pi_size > 0) {
- X if (BufferSize > InSize.pi_size) {
- X BufferSize = InSize.pi_size;
- X } /* if buffer now holds it all */
- X
- X (void) bcopy(InBase, OutBase, (unsigned) BufferSize); /* silly new limitation */
- X
- X if ((ReallyWrote = write(OutPut, OutBase, BufferSize)) != BufferSize) {
- X Perror("writing output:");
- X exit(1);
- X } /* on error writing */
- X
- X InSize.pi_size -= ReallyWrote;
- X InBase += ReallyWrote;
- X } /* while data to write */
- X } /* if mapping output */
- X
- X } else { /* not mapping input */
- X
- X if (OutBase != ((char *) NULL)) { /* but mapping output */
- X int ReallyRead = 1;
- X
- X InBase = malloc((unsigned) BufferSize);
- X
- X while (ReallyRead != 0 && OutSize.pi_size > 0) {
- X if (BufferSize > OutSize.pi_size) {
- X BufferSize = OutSize.pi_size;
- X } /* if buffer now holds it all */
- X
- X if ((ReallyRead = read(InPut, InBase, BufferSize)) == -1) {
- X Perror("reading input:");
- X exit(1);
- X } /* on error reading */
- X
- X (void) bcopy(InBase, OutBase, (unsigned) ReallyRead);
- X
- X OutSize.pi_size -= ReallyRead;
- X OutBase += ReallyRead;
- X } /* while data to write */
- X
- X } else { /* mapping nothing, should use cat instead */
- X if (Silent == 0) {
- X (void) fprintf(stderr, "%s: not mapping anything. use cat instead.\n", argv[0]);
- X } /* not silent */
- X
- X exit(1);
- X } /* if mapping output */
- X } /* if mapping input */
- X
- X exit(0);
- X} /* main() */
- X
- X/*
- X * $Log: mcat.c,v $
- X * Revision 1.2 88/03/21 00:42:41 rich
- X * now double bufferred to cover dynix 3.0.4 limitation.
- X *
- X * Revision 1.1 87/11/27 18:06:45 rich
- X * Initial revision
- X *
- X *
- X * Local Variables:
- X * comment-column: 0
- X * fill-column: 130
- X * fill-prefix: " * "
- X * mode: c
- X * version-control: t
- X * End:
- X */
- X
- X/* end of mcat.c */
- END-of-mcat.c
- exit
-
-